package com.example.video_encoder;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class MainActivity extends AppCompatActivity {
    private SoftwareEncoder mSoftwareEncoder;
    private EncoderThread mEncoderThread;
    private TextView mVideoFrameCount;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
        }
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        mVideoFrameCount = findViewById(R.id.sample_text);
        mSoftwareEncoder = new SoftwareEncoder();

        mVideoFrameCount.setText(mSoftwareEncoder.getString());

        findViewById(R.id.start).setOnClickListener((v)->{
            mEncoderThread = new EncoderThread();
            mEncoderThread.start();
        });
        findViewById(R.id.stop).setOnClickListener((v)->{
            mEncoderThread.mExit = true;
            try {
                mEncoderThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                mEncoderThread = null;
            }
        });
    }

    class EncoderThread extends Thread {
        public boolean mExit = false;
        private int mWidth = 1280;
        private int mHeight = 720;
        private byte[] mNalData = null;
        private byte[] mI420Data = null;
        @Override
        public void run() {
            super.run();
            int index = 0;
            int nal_size = 0;
            mNalData = new byte[mWidth * mHeight * 8];
            mI420Data = new byte[mWidth * mHeight * 3 / 2];

            mSoftwareEncoder.start(mWidth, mHeight);
            for (int i = 0; i < mHeight; ++i) {
                for (int j = 0; j < mWidth; ++j) {
                    mI420Data[i * mWidth + j] = 0;
                }
            }
            for (int i = 0; i < mHeight / 2; ++i) {
                for (int j = 0; j < mWidth / 2; ++j) {
                    mI420Data[mHeight * mWidth + i * mWidth/2 + j] = 0;
                }
            }
            for (int i = 0; i < mHeight / 2; ++i) {
                for (int j = 0; j < mWidth / 2; ++j) {
                    mI420Data[mHeight * mWidth * 5 / 4 + i * mWidth/2 + j] = 0;
                }
            }
            String filename = Environment.getExternalStorageDirectory().getAbsolutePath() + "/haima.h264";

            FileChannel fos = null;
            try {
                fos = new FileOutputStream(filename).getChannel();
            } catch (IOException e) {
                e.printStackTrace();
            }
            File yuv_file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                    + "/Cisco_Absolute_Power_1280x720_30fps.yuv");
            int yuv_file_offset = 0;
            int yuv_frame_size = mHeight * mWidth * 3 / 2;
            int yuv_file_end;
            FileInputStream yuv_input_stream = null;
            try {
                yuv_input_stream = new FileInputStream(yuv_file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            while (!mExit) {
                index++;
                try {
                    yuv_file_end = yuv_input_stream.read(mI420Data);
                    if (yuv_file_end != yuv_frame_size) {
                        break;
                    }

                    nal_size = mSoftwareEncoder.encode(mI420Data, mNalData);
                    if (nal_size > 0) {
                        fos.write(ByteBuffer.wrap(mNalData,0,nal_size));
                    }
                    Log.d("video encoder", "frame indext " + index);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                yuv_input_stream.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            mSoftwareEncoder.stop();
            Log.d("video encoder", "encode is stop");
        }
    }
}

